﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Certify.Core.Management.Access;
using Certify.Management;

namespace Certify.Models.Hub
{
    public class StandardRoles
    {
        internal static Role BackupOperator { get; } = new Role("backup_operator_role", "Backup Operator", "Can perform import and export operations",
            policies: [
                StandardPolicies.ManagedInstanceSystemExport,
                StandardPolicies.ManagedInstanceSystemImport
            ]);

        public static Role Administrator { get; } = new Role("sysadmin_role", "Administrator", "Certify Server Administrator",
            policies: [
                     StandardPolicies.ManagementHubAdmin,
                     StandardPolicies.ManagedItemAdmin,
                     StandardPolicies.CertificateAuthorityAdmin,
                     StandardPolicies.AcmeAccountAdmin,
                     StandardPolicies.StoredCredentialAdmin,
                     StandardPolicies.ManagedChallengeAdmin,
                     StandardPolicies.AccessAdmin,
                     StandardPolicies.OidcAdmin,
                     StandardPolicies.AccessTokenAdmin,
                     StandardPolicies.CertificateConsumer,
                     StandardPolicies.ManagedInstanceSystemExport,
                     StandardPolicies.ManagedInstanceSystemImport,
                     StandardPolicies.TagAdmin,
                     StandardPolicies.ManagedLicenseAdmin,
                     StandardPolicies.SystemUser
                    ]);

        public static Role CertificateManager { get; } = new Role("cert_manager_role", "Certificate Manager", "Can manage and administer all certificates",
            policies: [
                StandardPolicies.ManagementHubReader,
                StandardPolicies.ManagedItemAdmin,
                StandardPolicies.StoredCredentialAdmin,
                StandardPolicies.CertificateConsumer,
                StandardPolicies.SystemUser
                    ]);
        public static Role HubViewer { get; } = new Role("hub_viewer_role", "Hub Viewer", "Can view all hub managed certificates and summary information",
            policies: [
                StandardPolicies.ManagementHubReader,
                StandardPolicies.SystemUser
            ]);

        public static Role CertificateConsumer { get; } = new Role("cert_consumer_role", "Certificate Consumer", "User of a given certificate", policies: [StandardPolicies.CertificateConsumer]);

        public static Role StoredCredentialConsumer { get; } = new Role("storedcredential_consumer_role", "Stored Credential Fetch Consumer", "Can fetch a decrypted stored credential", policies: [StandardPolicies.StoredCredentialConsumer]);
        public static Role ManagedChallengeAdmin { get; } = new Role("managedchallenge_admin_role", "Managed Challenge Admin", "Can administer managed challenge configurations", policies: [StandardPolicies.ManagedChallengeAdmin]);
        public static Role ManagedChallengeConsumer { get; } = new Role("managedchallenge_consumer_role", "Managed Challenge Consumer", "Can perform specific managed challenges", policies: [StandardPolicies.ManagedChallengeConsumer]);

        public static Role ManagedInstance { get; } = new Role("managedinstance_role", "Hub Managed Instance", "Can join the hub and be managed via the hub.", policies: [StandardPolicies.ManagedInstance]);
        public static Role ManagedAcmeConsumer { get; } = new Role("managedacme_consumer_role", "Managed ACME Consumer", "Can use managed ACME services via the hub.", policies: [StandardPolicies.ManagedAcmeConsumer]);
    }

    public class StandardIdentityProviders
    {
        /// <summary>
        /// Identity is stored in the app/service database
        /// </summary>
        public const string INTERNAL = "INTERNAL";

        /// <summary>
        /// Identity is provided by the OS
        /// </summary>
        public const string OS = "OS";

        /// <summary>
        /// Identity is stored in LDAP/AD
        /// </summary>
        public const string LDAP = "LDAP";

        /// <summary>
        /// Identity is provided by OpenID
        /// </summary>
        public const string OID = "OID";
    }

    public class ResourceTypes
    {
        public const string System = "system";
        public const string SecurityPrincipal = "securityprincipal";
        public const string Role = "role";
        public const string AccessToken = "accesstoken";
        public const string Domain = "domain";
        public const string ManagedItem = "manageditem";
        public const string Certificate = "certificate";
        public const string StoredCredential = "storedcredential";
        public const string CertificateAuthority = "ca";
        public const string AcmeAccount = "acmeaccount";
        public const string ManagedChallenge = "managedchallenge";
        public const string ManagedAcme = "managedacme";
        public const string ManagedInstance = "managedinstance";
        public const string ManagedLicense = "managedlicense";
        public const string OidcProvider = "oidcprovider";
        public const string Target = "target";
        public const string ChallengeProvider = "challengeprovider";
        public const string DeploymentTask = "deploymenttask";
        public const string Tag = "tag";
    }

    public static class StandardResourceActions
    {
        public const string CertificateDownload = "certificate_download_action";
        public const string CertificateKeyDownload = "certificate_key_download_action";

        public const string ManagedItemRequest = "manageditem_requester_action";
        public const string ManagedItemAdd = "manageditem_add_action";
        public const string ManagedItemList = "manageditem_list_action";
        public const string ManagedItemUpdate = "manageditem_update_action";
        public const string ManagedItemDelete = "manageditem_delete_action";
        public const string ManagedItemTest = "manageditem_test_action";
        public const string ManagedItemRenew = "manageditem_renew_action";
        public const string ManagedItemTaskAdd = "manageditem_task_add_action";
        public const string ManagedItemTaskUpdate = "manageditem_task_update_action";
        public const string ManagedItemTaskDelete = "manageditem_task_delete_action";
        public const string ManagedItemLogView = "manageditem_log_view_action";

        public const string CertificateAuthorityAdd = "ca_add_action";
        public const string CertificateAuthorityUpdate = "ca_update_action";
        public const string CertificateAuthorityDelete = "ca_delete_action";
        public const string CertificateAuthorityList = "ca_list_action";

        public const string AcmeAccountAdd = "acmeaccount_add_action";
        public const string AcmeAccountUpdate = "acmeaccount_update_action";
        public const string AcmeAccountDelete = "acmeaccount_delete_action";
        public const string AcmeAccountList = "acmeaccount_list_action";

        public const string StoredCredentialAdd = "storedcredential_add_action";
        public const string StoredCredentialUpdate = "storedcredential_update_action";
        public const string StoredCredentialDelete = "storedcredential_delete_action";
        public const string StoredCredentialList = "storedcredential_list_action";
        public const string StoredCredentialReadSecret = "storedcredential_consumer_action";

        public const string SecurityPrincipalList = "securityprincipal_list_action";
        public const string SecurityPrincipalAdd = "securityprincipal_add_action";
        public const string SecurityPrincipalUpdate = "securityprincipal_update_action";
        public const string SecurityPrincipalUpdateAssignedRoles = "securityprincipal_update_assignedroles_action";
        public const string SecurityPrincipalDelete = "securityprincipal_delete_action";
        public const string SecurityPrincipalPasswordUpdate = "securityprincipal_password_update_action";
        public const string SecurityPrincipalPasswordValidate = "securityprincipal_password_validate_action";
        public const string SecurityPrincipalCheckAccess = "securityprincipal_access_check_action";

        public const string RoleList = "role_list_action";

        public const string ManagedChallengeList = "managedchallenge_list_action";
        public const string ManagedChallengeUpdate = "managedchallenge_update_action";
        public const string ManagedChallengeDelete = "managedchallenge_update_action";
        public const string ManagedChallengeRequest = "managedchallenge_request_action";
        public const string ManagedChallengeCleanup = "managedchallenge_cleanup_action";

        public const string ManagementHubInstancesList = "managementhub_instances_list_action";
        public const string ManagementHubInstanceJoin = "managementhub_instance_join_action";
        public const string ManagementHubInstanceDelete = "managementhub_instance_delete_action";
        public const string ManagementHubInstanceAdd = "managementhub_instance_add_action";
        public const string ManagementHubInstanceUpdate = "managementhub_instance_update_action";

        public const string ManagementHubInstanceExport = "managementhub_instance_export_action";
        public const string ManagementHubInstanceImport = "managementhub_instance_import_action";

        public const string AccessTokenList = "accesstoken_list_action";
        public const string AccessTokenAdd = "accesstoken_add_action";
        public const string AccessTokenUpdate = "accesstoken_update_action";
        public const string AccessTokenDelete = "accesstoken_delete_action";

        public const string SystemGeneralAction = "system_general_action";

        public const string SystemStatusList = "system_status_list_action";
        public const string SystemServiceConfigList = "system_serviceconfig_list_action";
        public const string SystemCoreSettingsList = "system_coresettings_list_action";
        public const string SystemServiceConfigUpdate = "system_serviceconfig_update_action";
        public const string SystemCoreSettingsUpdate = "system_coresettings_update_action";

        public const string TargetIPAddressesList = "target_ipaddresses_list_action";
        public const string TargetTypesList = "target_types_list_action";
        public const string TargetServiceItemsList = "target_serviceitems_list_action";
        public const string TargetServiceItemIdentifiersList = "target_serviceitemidentifiers_list_action";

        public const string ChallengeProviderList = "challengeprovider_list_action";
        public const string ChallengeProviderDnsZonesList = "challengeprovider_dnszones_list_action";

        public const string DeploymentTaskExecute = "deploymenttask_execute_action";
        public const string DeploymentTaskListProviders = "deploymenttask_list_providers_action";

        public const string TagAdd = "managementhub_tag_add_action";
        public const string TagDelete = "managementhub_tag_delete_action";
        public const string TagUpdate = "managementhub_tag_update_action";
        public const string TagList = "managementhub_tag_list_action";

        public const string ManagedLicenseList = "managedlicense_list_action";
        public const string ManagedLicenseAdd = "managedlicense_add_action";
        public const string ManagedLicenseUpdate = "managedlicense_update_action";
        public const string ManagedLicenseDelete = "managedlicense_delete_action";
        public const string ManagedLicenseActivate = "managedlicense_activate_action";
        public const string ManagedLicenseDeactivate = "managedlicense_deactivate_action";
        public const string ManagedLicenseStatus = "managedlicense_status_action";

        public const string ManagedAcmePerformOrder = "managedacme_order_action";

        public const string OidcProviderList = "oidcprovider_list_action";
        public const string OidcProviderAdd = "oidcprovider_add_action";
        public const string OidcProviderUpdate = "oidcprovider_update_action";
        public const string OidcProviderDelete = "oidcprovider_delete_action";

    }

    public class StandardPolicies
    {
        public const string AccessAdmin = "access_admin_policy";
        public const string OidcAdmin = "oidc_admin_policy";
        public const string AccessTokenAdmin = "accesstoken_admin_policy";
        public const string ManagedItemAdmin = "manageditem_admin_policy";
        public const string CertificateConsumer = "certificate_consumer_policy";
        public const string CertificateAuthorityAdmin = "ca_admin_policy";
        public const string AcmeAccountAdmin = "acmeaccount_admin_policy";
        public const string StoredCredentialAdmin = "storedcredential_admin_policy";
        public const string StoredCredentialConsumer = "storedcredential_consumer_policy";
        public const string ManagedChallengeConsumer = "managedchallenge_consumer_policy";
        public const string ManagedChallengeAdmin = "managedchallenge_admin_policy";
        public const string ManagementHubAdmin = "managementhub_admin_policy";
        public const string ManagementHubReader = "managementhub_reader_policy";
        public const string ManagedInstance = "managementhub_managedinstance_policy";
        public const string ManagedInstanceSystemImport = "system_import_policy";
        public const string ManagedInstanceSystemExport = "system_export_policy";
        public const string ManagedLicenseAdmin = "managedlicense_admin_policy";
        public const string ManagedAcmeConsumer = "managedacme_consumer_policy";
        public const string SystemUser = "system_user_policy";
        public const string TagAdmin = "tag_admin_policy";

    }

    public static class Policies
    {
        public static List<Role> GetStandardRoles()
        {
            return
            [
                StandardRoles.Administrator,
                StandardRoles.CertificateManager,
                StandardRoles.CertificateConsumer,
                StandardRoles.StoredCredentialConsumer,
                StandardRoles.ManagedChallengeAdmin,
                StandardRoles.ManagedChallengeConsumer,
                StandardRoles.ManagedAcmeConsumer,
                StandardRoles.HubViewer,
                StandardRoles.ManagedInstance,
                StandardRoles.BackupOperator
            ];
        }

        public static List<ResourceAction> GetStandardResourceActions()
        {
            return [

                new(StandardResourceActions.CertificateDownload, "Certificate Download", ResourceTypes.Certificate),
                new(StandardResourceActions.CertificateKeyDownload, "Certificate Private Key Download", ResourceTypes.Certificate),

                new(StandardResourceActions.CertificateAuthorityAdd, "Add New Certificate Authority", ResourceTypes.CertificateAuthority),
                new(StandardResourceActions.CertificateAuthorityUpdate, "Update Certificate Authority", ResourceTypes.CertificateAuthority),
                new(StandardResourceActions.CertificateAuthorityDelete, "Delete Certificate Authority", ResourceTypes.CertificateAuthority),
                new(StandardResourceActions.CertificateAuthorityList, "List Certificate Authority", ResourceTypes.CertificateAuthority),

                new(StandardResourceActions.AcmeAccountAdd, "Add New ACME Account", ResourceTypes.AcmeAccount),
                new(StandardResourceActions.AcmeAccountUpdate, "Update ACME Account", ResourceTypes.AcmeAccount),
                new(StandardResourceActions.AcmeAccountDelete, "Delete ACME Account", ResourceTypes.AcmeAccount),
                new(StandardResourceActions.AcmeAccountList, "List ACME Accounts", ResourceTypes.AcmeAccount),

                new(StandardResourceActions.StoredCredentialAdd, "Add New Stored Credential", ResourceTypes.StoredCredential),
                new(StandardResourceActions.StoredCredentialUpdate, "Update Stored Credential", ResourceTypes.StoredCredential),
                new(StandardResourceActions.StoredCredentialDelete, "Delete Stored Credential", ResourceTypes.StoredCredential),
                new(StandardResourceActions.StoredCredentialList, "List Stored Credentials", ResourceTypes.StoredCredential),
                new(StandardResourceActions.StoredCredentialReadSecret, "Fetch Decrypted Stored Credential", ResourceTypes.StoredCredential),

                new(StandardResourceActions.SecurityPrincipalList, "List Security Principals", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalAdd, "Add New Security Principal", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalUpdate,"Update Security Principals", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalUpdateAssignedRoles,"Update Security Principal Assigned Roles", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalPasswordUpdate, "Update Security Principal Passwords", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalDelete, "Delete Security Principal", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalCheckAccess, "Check Security Principal Access", ResourceTypes.SecurityPrincipal),
                new(StandardResourceActions.SecurityPrincipalPasswordValidate, "Validate Security Principal Passwords", ResourceTypes.SecurityPrincipal),

                new(StandardResourceActions.AccessTokenAdd, "Add Access Token", ResourceTypes.AccessToken),
                new(StandardResourceActions.AccessTokenDelete, "Delete Access Token", ResourceTypes.AccessToken),
                new(StandardResourceActions.AccessTokenList, "List Access Tokens", ResourceTypes.AccessToken),
                new(StandardResourceActions.AccessTokenUpdate, "Update Access Token", ResourceTypes.AccessToken),

                new(StandardResourceActions.RoleList, "List Roles", ResourceTypes.Role),

                new(StandardResourceActions.ManagedItemRequest, "Request New Managed Items", ResourceTypes.ManagedItem),

                new(StandardResourceActions.ManagedItemList, "List Managed Items", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemAdd, "Add Managed Items", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemUpdate, "Update Managed Items", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemDelete, "Delete Managed Items", ResourceTypes.ManagedItem),

                new(StandardResourceActions.ManagedItemTest, "Test Managed Item Renewal Checks", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemRequest, "Request Managed Items", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemRenew, "Renew Managed Items", ResourceTypes.ManagedItem),

                new(StandardResourceActions.ManagedItemTaskAdd, "Add Managed Item Tasks", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemTaskUpdate, "Update Managed Item Tasks", ResourceTypes.ManagedItem),
                new(StandardResourceActions.ManagedItemTaskDelete, "Delete Managed Item Tasks", ResourceTypes.ManagedItem),

                new(StandardResourceActions.ManagedItemLogView, "View/Download Managed Item Log", ResourceTypes.ManagedItem),

                new(StandardResourceActions.ManagedChallengeList, "List managed challenges", ResourceTypes.ManagedChallenge),
                new(StandardResourceActions.ManagedChallengeUpdate, "Update managed challenge", ResourceTypes.ManagedChallenge),
                new(StandardResourceActions.ManagedChallengeDelete, "Delete managed challenge", ResourceTypes.ManagedChallenge),
                new(StandardResourceActions.ManagedChallengeRequest, "Request to perform a managed challenge response", ResourceTypes.ManagedChallenge),
                new(StandardResourceActions.ManagedChallengeCleanup, "Cleanup managed challenges", ResourceTypes.ManagedChallenge),

                new(StandardResourceActions.ManagementHubInstancesList, "List managed instances", ResourceTypes.ManagedInstance),
                new(StandardResourceActions.ManagementHubInstanceJoin, "Join management hub as a managed instance", ResourceTypes.ManagedInstance),
                new(StandardResourceActions.ManagementHubInstanceDelete, "Delete managed instance from the hub", ResourceTypes.ManagedInstance),
                new(StandardResourceActions.ManagementHubInstanceAdd, "Add managed instance details to the hub", ResourceTypes.ManagedInstance),
                new(StandardResourceActions.ManagementHubInstanceUpdate, "Update managed instance detail in the hub", ResourceTypes.ManagedInstance),

                new(StandardResourceActions.ManagementHubInstanceExport, "Export system configuration", ResourceTypes.ManagedInstance),
                new(StandardResourceActions.ManagementHubInstanceImport, "Import system configuration", ResourceTypes.ManagedInstance),

                new(StandardResourceActions.SystemStatusList, "List system status", ResourceTypes.System),
                new(StandardResourceActions.SystemServiceConfigList, "List system service configuration", ResourceTypes.System),
                new(StandardResourceActions.SystemCoreSettingsList, "List system core settings", ResourceTypes.System),
                new(StandardResourceActions.SystemServiceConfigUpdate, "Update system service configuration", ResourceTypes.System),
                new(StandardResourceActions.SystemCoreSettingsUpdate, "Update system core settings", ResourceTypes.System),

                new(StandardResourceActions.TargetIPAddressesList, "List target IP addresses", ResourceTypes.Target),
                new(StandardResourceActions.TargetTypesList, "List target types", ResourceTypes.Target),
                new(StandardResourceActions.TargetServiceItemsList, "List target service items", ResourceTypes.Target),
                new(StandardResourceActions.TargetServiceItemIdentifiersList, "List target service item identifiers", ResourceTypes.Target),

                new(StandardResourceActions.ChallengeProviderList, "List challenge providers", ResourceTypes.ChallengeProvider),
                new(StandardResourceActions.ChallengeProviderDnsZonesList, "List challenge provider DNS zones", ResourceTypes.ChallengeProvider),

                new(StandardResourceActions.DeploymentTaskExecute, "Execute deployment task", ResourceTypes.DeploymentTask),
                new(StandardResourceActions.DeploymentTaskListProviders, "List deployment task providers", ResourceTypes.DeploymentTask),

                new(StandardResourceActions.TagList, "List item tags", ResourceTypes.Tag),
                new(StandardResourceActions.TagAdd, "Add item tags", ResourceTypes.Tag),
                new(StandardResourceActions.TagUpdate, "Update item tags", ResourceTypes.Tag),
                new(StandardResourceActions.TagDelete, "Delete item tags", ResourceTypes.Tag),

                new(StandardResourceActions.ManagedLicenseList, "List managed licenses", ResourceTypes.ManagedLicense),
                new(StandardResourceActions.ManagedLicenseAdd, "Add managed license", ResourceTypes.ManagedLicense),
                new(StandardResourceActions.ManagedLicenseUpdate, "Update managed license", ResourceTypes.ManagedLicense),
                new(StandardResourceActions.ManagedLicenseDelete, "Delete managed license", ResourceTypes.ManagedLicense),
                new(StandardResourceActions.ManagedLicenseActivate, "Apply managed license to an instance", ResourceTypes.ManagedLicense),
                new(StandardResourceActions.ManagedLicenseDeactivate, "Remove managed license from an instance", ResourceTypes.ManagedLicense),
                new(StandardResourceActions.ManagedLicenseStatus, "Get status for a managed license", ResourceTypes.ManagedLicense),

                new(StandardResourceActions.ManagedAcmePerformOrder, "Perform managed acme order", ResourceTypes.ManagedAcme),

                new(StandardResourceActions.OidcProviderList, "List Oidc Provider licenses", ResourceTypes.OidcProvider),
                new(StandardResourceActions.OidcProviderAdd, "Add Oidc Provider", ResourceTypes.OidcProvider),
                new(StandardResourceActions.OidcProviderUpdate, "Update Oidc Provider", ResourceTypes.OidcProvider),
                new(StandardResourceActions.OidcProviderDelete, "Delete Oidc Provider", ResourceTypes.OidcProvider),

            ];
        }

        public static List<ResourcePolicy> GetStandardPolicies()
        {
            return [
                new() {
                    Id = StandardPolicies.ManagedItemAdmin,
                    Title = "Managed Item Administration",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.ManagedItemList,
                        StandardResourceActions.ManagedItemAdd,
                        StandardResourceActions.ManagedItemUpdate,
                        StandardResourceActions.ManagedItemDelete,
                        StandardResourceActions.ManagedItemTest,
                        StandardResourceActions.ManagedItemRequest,
                        StandardResourceActions.ManagedItemRenew,
                        StandardResourceActions.ManagedItemTaskAdd,
                        StandardResourceActions.ManagedItemTaskUpdate,
                        StandardResourceActions.ManagedItemTaskDelete,
                        StandardResourceActions.ManagedItemLogView,
                        StandardResourceActions.TargetIPAddressesList,
                        StandardResourceActions.TargetServiceItemIdentifiersList,
                        StandardResourceActions.TargetServiceItemsList,
                        StandardResourceActions.TargetTypesList,
                        StandardResourceActions.ChallengeProviderList,
                        StandardResourceActions.ChallengeProviderDnsZonesList,
                        StandardResourceActions.DeploymentTaskExecute,
                        StandardResourceActions.DeploymentTaskListProviders
                    ]
                },
                new() {
                    Id = StandardPolicies.AccessAdmin,
                    Title = "Access Control Administration",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.SecurityPrincipalList,
                        StandardResourceActions.SecurityPrincipalAdd,
                        StandardResourceActions.SecurityPrincipalUpdate,
                        StandardResourceActions.SecurityPrincipalDelete,
                        StandardResourceActions.SecurityPrincipalPasswordUpdate,
                        StandardResourceActions.SecurityPrincipalUpdateAssignedRoles

                    ]
                },
                 new() {
                     Id = StandardPolicies.OidcAdmin,
                     Title = "Oidc Provider Administration",
                     SecurityPermissionType = SecurityPermissionType.ALLOW,
                     ResourceActions = [
                         StandardResourceActions.OidcProviderList,
                         StandardResourceActions.OidcProviderAdd,
                         StandardResourceActions.OidcProviderUpdate,
                         StandardResourceActions.OidcProviderDelete,
                     ]
                 },
                new() {
                     Id = StandardPolicies.AccessTokenAdmin,
                     Title = "Access Token Administration",
                     SecurityPermissionType = SecurityPermissionType.ALLOW,
                     ResourceActions = [
                         StandardResourceActions.AccessTokenList,
                         StandardResourceActions.AccessTokenAdd,
                         StandardResourceActions.AccessTokenDelete,
                         StandardResourceActions.AccessTokenUpdate,
                     ]
                 },
                new() {
                    Id = StandardPolicies.CertificateConsumer,
                    Title = "Consume Certificates",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.CertificateDownload,
                        StandardResourceActions.CertificateKeyDownload
                    ]
                },
                new() {
                    Id = StandardPolicies.CertificateAuthorityAdmin,
                    Title = "Certificate Authority Administration",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.CertificateAuthorityAdd,
                        StandardResourceActions.CertificateAuthorityUpdate,
                        StandardResourceActions.CertificateAuthorityDelete,
                        StandardResourceActions.CertificateAuthorityList
                    ]
                },
                new() {
                    Id = StandardPolicies.AcmeAccountAdmin,
                    Title = "ACME Account Administration",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.AcmeAccountList,
                        StandardResourceActions.AcmeAccountAdd,
                        StandardResourceActions.AcmeAccountUpdate,
                        StandardResourceActions.AcmeAccountDelete
                    ]
                },
                new() {
                    Id = StandardPolicies.StoredCredentialAdmin,
                    Title = "Stored Credential Administration",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.StoredCredentialList,
                        StandardResourceActions.StoredCredentialAdd,
                        StandardResourceActions.StoredCredentialUpdate,
                        StandardResourceActions.StoredCredentialDelete
                    ]
                },
                new() {
                    Id = StandardPolicies.StoredCredentialConsumer,
                    Title = "Stored Credential Consumer",
                    Description = "Provides access to fetch a decrypted stored credential.",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    IsResourceSpecific = true,
                    ResourceActions = [
                        StandardResourceActions.StoredCredentialReadSecret
                    ]
                },
                new() {
                    Id = StandardPolicies.ManagedChallengeAdmin,
                    Title = "Managed Challenge Administration",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    ResourceActions = [
                        StandardResourceActions.ManagedChallengeList,
                        StandardResourceActions.ManagedChallengeUpdate,
                        StandardResourceActions.ManagedChallengeDelete
                    ]
                },
                new() {
                    Id = StandardPolicies.ManagedChallengeConsumer,
                    Title = "Managed Challenge Consumer",
                    Description = "Allows consumer to request that a managed challenge be performed.",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    IsResourceSpecific = true,
                    ResourceActions = [
                        StandardResourceActions.ManagedChallengeRequest,
                        StandardResourceActions.ManagedChallengeCleanup
                    ]
                },
                new() {
                    Id = StandardPolicies.ManagementHubAdmin,
                    Title = "Management Hub Admin",
                    Description = "Administer management hub.",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    IsResourceSpecific = true,
                    ResourceActions = [
                        StandardResourceActions.ManagementHubInstancesList,
                        StandardResourceActions.ManagementHubInstanceAdd,
                        StandardResourceActions.ManagementHubInstanceUpdate,
                        StandardResourceActions.ManagementHubInstanceDelete,
                        StandardResourceActions.SystemStatusList,
                        StandardResourceActions.SystemCoreSettingsList,
                        StandardResourceActions.SystemCoreSettingsUpdate,
                        StandardResourceActions.SystemServiceConfigList,
                        StandardResourceActions.SystemServiceConfigUpdate,

                    ]
                },
                new() {
                    Id = StandardPolicies.ManagementHubReader,
                    Title = "Management Hub Reader",
                    Description = "View management hub.",
                    SecurityPermissionType = SecurityPermissionType.ALLOW,
                    IsResourceSpecific = true,
                    ResourceActions = [
                        StandardResourceActions.ManagementHubInstancesList,
                        StandardResourceActions.AcmeAccountList,
                        StandardResourceActions.CertificateAuthorityList,
                        StandardResourceActions.ChallengeProviderList,
                        StandardResourceActions.DeploymentTaskListProviders,
                        StandardResourceActions.ManagedChallengeList,
                        StandardResourceActions.ManagedItemList,
                        StandardResourceActions.StoredCredentialList,
                        StandardResourceActions.RoleList,
                        StandardResourceActions.TagList,
                        StandardResourceActions.ManagementHubInstancesList,
                        StandardResourceActions.TargetTypesList,
                        StandardResourceActions.SystemStatusList,
                        StandardResourceActions.SystemCoreSettingsList,
                        StandardResourceActions.SystemServiceConfigList,
                    ]
                },
                new() {
                     Id = StandardPolicies.ManagedInstance,
                     Title = "Management Hub Managed Instance",
                     Description = "Join management hub and allow to be managed by hub.",
                     SecurityPermissionType = SecurityPermissionType.ALLOW,
                     IsResourceSpecific = true,
                     ResourceActions = [
                         StandardResourceActions.ManagementHubInstanceJoin
                     ]
                 },
                  new() {
                 Id = StandardPolicies.ManagedInstanceSystemImport,
                 Title = "Instance Configuration Import",
                 Description = "Import system configuration and apply to a target instance",
                 SecurityPermissionType = SecurityPermissionType.ALLOW,
                 IsResourceSpecific = true,
                 ResourceActions = [
                     StandardResourceActions.ManagementHubInstanceImport
                 ]
             },
              new() {
                 Id = StandardPolicies.ManagedInstanceSystemExport,
                 Title = "Instance Configuration Export",
                 Description = "Export system configuration for a target instance",
                 SecurityPermissionType = SecurityPermissionType.ALLOW,
                 IsResourceSpecific = true,
                 ResourceActions = [
                     StandardResourceActions.ManagementHubInstanceExport
                 ]
              },
              new() {
                 Id = StandardPolicies.SystemUser,
                 Title = "System User",
                 Description = "Perform general system use actions",
                 SecurityPermissionType = SecurityPermissionType.ALLOW,
                 IsResourceSpecific = true,
                 ResourceActions = [
                     StandardResourceActions.SecurityPrincipalCheckAccess,
                     StandardResourceActions.SecurityPrincipalPasswordValidate,
                     StandardResourceActions.RoleList,
                 ]
              },
              new() {
                  Id = StandardPolicies.TagAdmin,
                  Title = "Tag Administration",
                  SecurityPermissionType = SecurityPermissionType.ALLOW,
                  ResourceActions = [
                      StandardResourceActions.TagList,
                      StandardResourceActions.TagAdd,
                      StandardResourceActions.TagUpdate,
                      StandardResourceActions.TagDelete
                  ]
              },
              new() {
                 Id = StandardPolicies.ManagedAcmeConsumer,
                 Title = "Managed Acme Consumer",
                 SecurityPermissionType = SecurityPermissionType.ALLOW,
                 ResourceActions = [
                     StandardResourceActions.ManagedAcmePerformOrder
                 ]
             },
                new() {
       Id = StandardPolicies.ManagedLicenseAdmin,
       Title = "Managed License Administration",
       SecurityPermissionType = SecurityPermissionType.ALLOW,
       ResourceActions = [
           StandardResourceActions.ManagedLicenseList,
           StandardResourceActions.ManagedLicenseAdd,
           StandardResourceActions.ManagedLicenseUpdate,
           StandardResourceActions.ManagedLicenseDelete,
           StandardResourceActions.ManagedLicenseActivate,
           StandardResourceActions.ManagedLicenseDeactivate,
           StandardResourceActions.ManagedLicenseStatus
       ]
   },
            ];
        }
    }

    public static class AccessControlConfig
    {
        /// <summary>
        /// Add/update standard system roles, policies and resource actions
        /// </summary>
        /// <param name="access"></param>
        /// <returns></returns>
        public static async Task UpdateStandardAccessConfig(IAccessControl access)
        {
            // setup roles with policies

            var adminSvcPrincipal = "admin_01";

            var actions = Policies.GetStandardResourceActions();

            foreach (var action in actions)
            {
                await access.AddResourceAction(adminSvcPrincipal, action, bypassIntegrityCheck: true);
            }

            // setup policies with actions

            var policies = Policies.GetStandardPolicies();

            // add policies to store
            foreach (var r in policies)
            {
                _ = await access.AddResourcePolicy(adminSvcPrincipal, r, bypassIntegrityCheck: true);
            }

            // setup roles with policies
            var roles = Policies.GetStandardRoles();

            foreach (var r in roles)
            {
                // add roles and policy assignments to store
                await access.AddRole(adminSvcPrincipal, r, bypassIntegrityCheck: true);
            }
        }

        public static async Task ConfigureStandardUsersAndRoles(IAccessControl access, ICredentialsManager creds)
        {
            // setup roles with policies
            await UpdateStandardAccessConfig(access);

            // setup standard security principals

            // admin user
            var adminSpId = "admin_01";
            var managedInstanceSpId = "managedinstance_sp_01";

            var users = await access.GetSecurityPrincipals(adminSpId);

            // add admin user if not already present
            if (!users.Any(u => u.Id == adminSpId))
            {
                var adminSp = new SecurityPrincipal
                {
                    Id = adminSpId,
                    Description = "Primary default admin",
                    PrincipalType = SecurityPrincipalType.User,
                    Username = Environment.GetEnvironmentVariable("CERTIFY_ADMIN_DEFAULTUSERNAME") ?? "admin",
                    Password = Environment.GetEnvironmentVariable("CERTIFY_ADMIN_DEFAULTPWD") ?? "changeme!",
                    Provider = StandardIdentityProviders.INTERNAL,
                    IsBuiltIn = true
                };

                await access.AddSecurityPrincipal(adminSp.Id, adminSp, bypassIntegrityCheck: true);
            }
            // get assigned roles for admin and update any missing roles
            var assignedRolesForAdmin = await access.GetAssignedRoles(adminSpId, adminSpId);

            // assign admin role to admin security principal
            var toBeAssignedRoles = new List<AssignedRole> {
                     // administrator
                     new AssignedRole{
                         Id= Guid.NewGuid().ToString(),
                         RoleId=StandardRoles.Administrator.Id,
                         SecurityPrincipalId=adminSpId
                     }
                };

            foreach (var r in toBeAssignedRoles)
            {
                if (assignedRolesForAdmin?.Any(a => a.RoleId == r.RoleId) != true)
                {
                    // add roles and policy assignments to store
                    await access.AddAssignedRole(adminSpId, r, bypassIntegrityCheck: true);
                }
            }

            // add managed instance service principal if not already present
            if (!users.Any(u => u.Id == managedInstanceSpId))
            {
                var managedInstanceServicePrincipal = new SecurityPrincipal
                {
                    Id = managedInstanceSpId,
                    Title = "Managed Instances Service Principal",
                    PrincipalType = SecurityPrincipalType.Application,
                    Provider = StandardIdentityProviders.INTERNAL,
                    IsBuiltIn = true
                };

                await access.AddSecurityPrincipal(adminSpId, managedInstanceServicePrincipal, bypassIntegrityCheck: true);

                // assign managed instance role to  security principal
                var assignedRoles = new List<AssignedRole> {

                    new AssignedRole{
                        Id= Guid.NewGuid().ToString(),
                        RoleId=StandardRoles.ManagedInstance.Id,
                        SecurityPrincipalId=managedInstanceSpId
                    }
                };

                foreach (var r in assignedRoles)
                {
                    // add roles and policy assignments to store
                    await access.AddAssignedRole(adminSpId, r, bypassIntegrityCheck: true);
                }

                // assign an API token for hub managed instances scoped to the managed instance role
                var assignedApiAccessToken = new AssignedAccessToken
                {
                    Id = Guid.NewGuid().ToString(),
                    SecurityPrincipalId = managedInstanceSpId,
                    Title = "Managed Instance Hub Joining Key",
                    AccessTokens = [
                        new AccessToken {
                            ClientId = managedInstanceSpId,
                            Description = "System Generated",
                            Secret = Guid.NewGuid().ToString().ToLowerInvariant(),
                            TokenType = AccessTokenTypes.Simple,
                            DateCreated = DateTime.UtcNow
                        }
                    ],
                    ScopedAssignedRoles = [
                        // scope assigned role is the id for AssignedRole (not the role id itself)
                        assignedRoles.First(a=>a.RoleId==StandardRoles.ManagedInstance.Id).Id
                    ],
                };

                await access.AddAssignedAccessToken(adminSpId, assignedApiAccessToken);
            }

            // if we don't have a stored credential as a client secret for the managed instance to join it's own hub, create one
            // direct instances don't really need this, but remote backends do so they can join back to their own hub.
            var existingJoiningKey = await creds.GetUnlockedCredential("_ManagementHubJoiningKey");
            if (existingJoiningKey == null)
            {
                var assignedTokens = await access.GetAssignedAccessTokens(contextUserId: adminSpId);
                var token = assignedTokens.First(t => t.Title == "Managed Instance Hub Joining Key")?.AccessTokens?.First();

                if (token != null)
                {
                    var clientSecret = new ClientSecret { ClientId = token.ClientId, Secret = token.Secret };
                    await creds.Update(new Config.StoredCredential
                    {
                        StorageKey = "_ManagementHubJoiningKey",
                        ProviderType = StandardAuthTypes.STANDARD_AUTH_MGMTHUB,
                        Title = "Management Hub Joining Key",
                        Secret = System.Text.Json.JsonSerializer.Serialize(clientSecret)
                    });
                }
            }
        }
    }
}
